/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package argtrust.logic;

import java.util.ArrayList;
import java.util.List;
import aima.core.logic.fol.parsing.ast.Sentence;

/**
 *
 * @author Yuqing Tang
 */
public class InferenceRule {

    private List<Sentence> mPremises;
    private Sentence mConclusion;

    public InferenceRule() {
        mPremises = null;
    }

    public InferenceRule(InferenceRule orig) {
        mPremises = new ArrayList<Sentence>(mPremises);
        mConclusion = orig.mConclusion.copy();
    }
    private int hashCode = 0;

    @Override
    public int hashCode() {
        if (0 == hashCode) {
            hashCode = 17;
            hashCode = 37 * hashCode + mConclusion.hashCode();
            if (mPremises != null) {
                for (Sentence p : mPremises) {
                    hashCode = 37 * hashCode + p.hashCode();
                }
            }
        }
        return hashCode;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final InferenceRule rhs = (InferenceRule) obj;
        boolean res = true;
        if (mConclusion != null) {
            res = res && mConclusion.equals(rhs.mConclusion);
        } else {
            res = res && rhs.mConclusion == null;
        }

        if (mPremises != null) {
            res = res && mPremises.equals(rhs.mPremises);
        } else {
            res = res && mPremises == null;
        }
        return res;
    }

    /**
     * For coding FOL compactness.
     * @param premise
     * @return
     */
    public InferenceRule P_(Sentence premise) {
        this.addPremise(premise);
        return this;
    }

    /**
     * For coding FOL compactness.
     * @param conclusion
     * @return
     */
    public InferenceRule C_(Sentence conclusion) {
        mConclusion = conclusion;
        return this;
    }

    public void addPremise(Sentence premise) {
        if (mPremises == null) {
            mPremises = new ArrayList<Sentence>();
        }
        mPremises.add(premise);

    }

    public void setConclusion(Sentence conclusion) {
        mConclusion = conclusion;
    }

    public void setPremises(List<Sentence> premises) {
        mPremises = premises;
    }

    public List<Sentence> getPremises() {
        return mPremises;
    }

    public Sentence getConclusion() {
        return mConclusion;
    }

    @Override
    public String toString() {
        String res = mConclusion.toString();
        res += " :- ";
        for (int i = 0; i < mPremises.size(); ++i) {
            Sentence p = mPremises.get(i);
            res += p.toString();
            if (i < mPremises.size() - 1) {
                res += ", ";
            }
        }

        return res;
    }

    public void debug_print(java.io.PrintStream out) {
        out.print(mConclusion.toString());
        out.println(" <= ");
        out.print("\t");

        for (int i = 0; i < mPremises.size(); ++i) {
            Sentence p = mPremises.get(i);
            out.print(p.toString());
            if (i < mPremises.size() - 1) {
                out.print(", ");
            }
        }
        out.println("||");
    }

    /**
     * Make the implication version of the rule.
     *
     * @return (p_1 \land p_2 \land ... \land p_n) -> conclusion
     */
    public Sentence sentencize() {
        if (mPremises.isEmpty()) {
            return mConclusion;
        }

        Sentence p_conj = mPremises.get(0);
        for (int i = 1; i < mPremises.size(); ++i) {
            p_conj = FOLFactory.and(p_conj, mPremises.get(i));
        }
        return FOLFactory.implies(p_conj, mConclusion);
    }
}
